#pragma once

#include "SocketTypes.hpp"

namespace socket_ops {

socket_type socket(int af, int type, int protocol);

socket_type accept(socket_type s, socket_addr_type* addr, socket_len_type* addrlen);

void setnonblocking(socket_type s);

int bind(socket_type s, const socket_addr_type* addr, socket_len_type addrlen);

int listen(socket_type s, int backlog);

int close(socket_type s);

int shutdown(socket_type s, int how);

int connect(socket_type s, const socket_addr_type* addr, socket_len_type addrlen);

int recv(socket_type s, char* buf, int len, int flags);

int send(socket_type s, const char* buf, int len, int flags);

} // namespace socketutil


socket_type socket_ops::socket(int af, int type, int protocol) {
    return ::socket(af, type, protocol);
}

socket_type socket_ops::accept(socket_type s, socket_addr_type* addr, socket_len_type* addrlen) {
    return ::accept(s, addr, addrlen);
}

void socket_ops::setnonblocking(socket_type s) {
#if defined(_WIN32)
    u_long iMode = 1;
    ioctlsocket(s, FIONBIO, &iMode);
#elif defined(__linux__)
    int flag = fcntl(s, F_GETFL, 0);
    fcntl(s, F_SETFL, flag | O_NONBLOCK);
#endif
}

int socket_ops::bind(socket_type s, const socket_addr_type* addr, socket_len_type addrlen) {
    return ::bind(s, addr, addrlen);
}

int socket_ops::listen(socket_type s, int backlog) {
    return ::listen(s, backlog);
}

int socket_ops::close(socket_type s) {
#if defined(_WIN32)
    return ::closesocket(s);
#elif defined(__linux__)
    return ::close(s);
#endif
}

int socket_ops::shutdown(socket_type s, int how) {
    return ::shutdown(s, how);
}

int socket_ops::connect(socket_type s, const socket_addr_type* addr, socket_len_type addrlen) {
    return ::connect(s, addr, addrlen);
}

int socket_ops::recv(socket_type s, char* buf, int len, int flags) {
    return ::recv(s, buf, len, flags);
}

int socket_ops::send(socket_type s, const char* buf, int len, int flags) {
    return ::send(s, buf, len, flags);
}
